from rest_framework.filters import OrderingFilter
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import viewsets, mixins, status
from rest_framework.decorators import action
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
# 导入文档生成类相关装饰器和类
from drf_spectacular.utils import extend_schema_view, extend_schema, OpenApiParameter
# 导入自定义登录状态认证类
from ..auth import JWTAuth
from home.models import Question, Answer
from home.serializers import QuestionSerializer, AnswerSerializer
from ..filters import QuestionFilter
from ..pagination import DynamicPagination


# 提问列表, 提问详情
@extend_schema_view(
    list=extend_schema(summary='获取提问列表',description="获取提问列表",tags=['提问'],
        parameters=[
            OpenApiParameter('keyword', str, OpenApiParameter.QUERY, description='搜索关键词'),
            OpenApiParameter('cate_id', str, OpenApiParameter.QUERY, description='分类id')
        ]
    ),
    retrieve=extend_schema(summary='获取单条提问详情',tags=['提问'],description='获取单条提问详情'),
    answers=extend_schema(summary='获取提问解答列表',tags=['提问'],description='获取提问解答列表'),
    mine=extend_schema(summary='获取当前登录账号发布的提问列表',tags=['提问'],description="获取当前登录账号发布的提问列表")
)
class QuestionListViewSet(mixins.ListModelMixin,mixins.RetrieveModelMixin,viewsets.GenericViewSet):

    # 配置数据集
    queryset = Question.objects.all()
    # 配置序列化器
    serializer_class = QuestionSerializer
    # 指定搜索基础工具类
    filter_backends = (DjangoFilterBackend,OrderingFilter,)
    # 指定自定义搜索工具类
    filterset_class = QuestionFilter
    # 指定排序字段   ordering=-id
    ordering_fields = ['id','create_time']
    # 设置分页类
    pagination_class = DynamicPagination
    # 设置路路径参数名称
    # lookup_url_kwarg = 'uuid'
    # 设置查询字段名称
    # lookup_field = 'uuid'

    # 重写retrieve方法, 实现访问一次, visit+1
    def retrieve(self,request,*args,**kwargs):
        # 接收路径参数
        pk=kwargs.get('pk')
        try:
            question=Question.objects.get(uuid=pk)
            # 阅读次数+1
            question.visit+=1
            # 保存更新
            question.save()
            # 手动序列化数据
            serializer = QuestionSerializer(question)
            return Response(serializer.data)
        except Question.DoesNotExist:
            return Response({'detail':'数据不存在'},status=status.HTTP_404_NOT_FOUND)

    # 获取当前登录者发布的提问
    @action(methods=['get'],detail=False,url_path="mine")
    def mine(self,request):
        # 手动验证登录状态
        # 创建登录认证类实例对象
        auth=JWTAuth()
        # 调用登录认证方法
        auth_user,token=auth.authenticate(request)
        if not auth_user:
            raise AuthenticationFailed('您还没有登录,请先登录')
        # 将账号信息挂载到请求对象上
        request.user=auth_user
        # 获取排序参数
        ordering=request.query_params.get('ordering')
        # 查询当前登录者发布的提问列表
        queryset=Question.objects.filter(user_id=request.user.id)
        # 如果提供了排序参数 and ordering in self.ordering_fields
        ordering_fields=[f'-{item}' for item in self.ordering_fields]
        print([*self.ordering_fields,*ordering_fields])
        if ordering and ordering in [*self.ordering_fields,*ordering_fields]:
            # 则进行排序
            queryset=queryset.order_by(ordering)
        # 手动实现分页
        # 创建分页类实例对象
        paginator=PageNumberPagination()
        # 调用分页方法:获取分页成功之后的数据对象
        page=paginator.paginate_queryset(queryset,request)
        # 判断分页是否成功, 如果分页失败, 则返回错误响应
        if isinstance(page,Response):
            # 直接返回错误响应
            return page
        # 序列化查询结果: 序列化分页成功之后的数据对象
        serializer = QuestionSerializer(page, many=True)
        # 响应查询结果: 必须调用paginator.get_paginator_response()返回响应结果
        # 通过分页类PageNumberPagination类的实例对象paginator调用实例方法get_paginated_response()返回响应对象
        return paginator.get_paginated_response(serializer.data)

    # 获取提问解答列表
    @action(methods=["GET"],detail=True)
    def answers(self,request,pk=None):
        # 根据que_id查询对应的解答列表
        queryset=Answer.objects.filter(que_id=pk)
        # 1-创建分页类实例对象
        paginator=PageNumberPagination()
        # 2-调用实例方法, 分页之后的数据对象
        page=paginator.paginate_queryset(queryset,request)
        # 分页失败, 如页码错误
        if isinstance(page, Response):
            # 返回错误响应
            return page
        # 将分页注之后的数据对象交给序列化器进行序列化
        serializer=AnswerSerializer(page,many=True)
        # 必须通过分页类实例对象paginator调用实例方法get_paginate_response()返回响应结果
        return paginator.get_paginated_response(data=serializer.data)

# 发布提问, 更新提问, 删除提问
@extend_schema_view(
    create=extend_schema(summary='发布提问',tags=['提问'],description='发布提问'),
    update=extend_schema(summary='更新提问(全量更新)',tags=['提问'],description='更新提问(全量更新)'),
    partial_update=extend_schema(summary='更新提问(部分更新)',tags=['提问'],description='更新提问(部分更新)'),
    destroy=extend_schema(summary='删除提问',tags=['提问'],description='删除提问')
)
class QuestionCreateViewSet(mixins.CreateModelMixin,mixins.DestroyModelMixin,mixins.UpdateModelMixin,viewsets.GenericViewSet):
    # 配置数据集
    queryset = Question.objects.all()
    # 配置序列化器
    serializer_class = QuestionSerializer
    # 指定登录状态认证类
    authentication_classes = (JWTAuth,)
    # 更新接口
    # serializer: 序列化器的实例对象
    def perform_update(self, serializer):
        # 判断当前登录账号和提问发布账号是否一致
        # self.request.user: 获取当前用户对象数据
        # self.get_object(): 获取当前要更新的数据对象
        if self.request.user.id == self.get_object().user_id:
            return serializer.save()
        raise AuthenticationFailed('当前登录账号id和要更新的提问发布者id不一致')

    # 新增接口
    # serializer: 系统参数, 表示序列化器的实例对象(包含了客户端发送的参数)
    def perform_create(self, serializer):
        # 设置发布者user_id
        serializer.validated_data['user_id'] = self.request.user.id
        # 执行新增操作
        serializer.save()

    # 删除接口
    def perform_destroy(self, instance):
        # 要删除的问题发布者必须和当前登录账号一致
        if self.request.user.id == instance.user_id:
            # 执行删除操作
           return instance.delete()
        raise AuthenticationFailed('暂无删除权限')




